// $Id: exception.hpp 2 2009-09-02 08:47:42Z joseph2002 $
/*
 * Copyright 2008-2009 Joseph Wu
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 *
 * For more information, see http://xpcomplus.sourceforge.net
 */

#ifndef XPCOM_EXCEPTION_HPP
#define XPCOM_EXCEPTION_HPP

#include <xpcom/config.hpp>
#include <exception>
#include <xpcom/result.hpp>

#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_PREFIX
#endif

namespace xpcom {

//
// Standard XPCOM exception class
//
class XPCOM_DECL exception : public std::exception
{
public:
    exception() throw();
    explicit exception(result code) throw();
    ~exception() throw() {}

    virtual const char* what() const throw();

    result code() const throw()
    {
        return code_;
    }

private:
    result code_;
};

namespace detail {

//
// throw_exception helper class.
//
struct throw_exception_t
{
    XPCOM_DECL void operator()() const;
    XPCOM_DECL void operator()(result code) const;
};

} // namespace xpcom::detail

inline result operator|(result code, const detail::throw_exception_t& te)
{
    if (code.failed())
        te(code);
    return code;
}

//
// throw_exception can by used in two different ways:
//
// First, the 'do or die' paradigm using overloaded operator|.
// Here try() is a function that returns a result. If try fails an exception
// will be thrown.
//
//  try() | throw_exception;
//
// Second, using throw_exception as an exception throwing function.
//
//  throw_exception();
//  throw_exception(some_result_value);
//
const detail::throw_exception_t throw_exception = {};

//
// Standard exception throws
//
XPCOM_DECL void throw_bad_alloc();
XPCOM_DECL void throw_bad_cast();
XPCOM_DECL void throw_invalid_argument(const char* msg = 0);
XPCOM_DECL void throw_length_error(const char* msg = 0);
XPCOM_DECL void throw_out_of_range(const char* msg = 0);
XPCOM_DECL void throw_runtime_error(const char* msg = 0);
XPCOM_DECL void throw_range_error(const char* msg = 0);

XPCOM_DECL void throw_not_implemented();

} // namespace xpcom

#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_SUFFIX
#endif

#endif // XPCOM_EXCEPTION_HPP
